import pygame
import random

SCREEN_RECT = pygame.Rect(0,0,480,700)
FRAME_INTERVAL = 10

HERO_BOMB_COUNT = 3
HERO_DEFAULT_MID_BOTTOM = (SCREEN_RECT.centerx,SCREEN_RECT.bottom - 90)

HERO_DEAD_EVENT = pygame.USEREVENT
HERO_POWER_OFF_EVENT = pygame.USEREVENT + 1
HERO_FIRE_EVENT = pygame.USEREVENT + 2
THROW_SUPPLY_EVENT = pygame.USEREVENT + 3
BULLET_ENHANCED_OFF_EVENT = pygame.USEREVENT + 4
#游戏窗口区域（矩形区域）



class GameSprite(pygame.sprite.Sprite):
    """游戏精灵类"""

    res_path ="./res/images/"    #图片资源路径
    def __init__(self, image_name, speed, *groups):

        super().__init__(*groups)
        self.image = pygame.image.load(self.res_path + image_name)
        self.rect = self.image.get_rect()   #矩形区域，默认在左上角
        self.speed = speed                  #移动速度

        self.mask = pygame.mask.from_surface(self.image)


    def update(self, *args):

        self.rect.y += self.speed           #改变y值实现垂直移动

class Background(GameSprite):
    """背景精灵类"""
    def __init__(self,is_alt, *groups):
        # 调用父类方法实现精灵的创建
        super().__init__("background.png", 1, *groups)
        # 判断是否是另一个精灵，如果是，需要设置初始位置
        if is_alt:
            self.rect.y = -self.rect.h              # 设置到游戏窗口正上方
    def update(self, *args):
        # 调用父类的方法实现向下移动
        super().update(*args)                       #向下移动
        # 判断是否移除游戏窗口，如果移出屏幕，将图像设置到屏幕的上方
        if self.rect.y >= self.rect.h:
            self.rect.y = -self.rect.h

class StatuButton(GameSprite):
    """状态按钮类"""
    def __init__(self, image_names, *groups):
        """构造方法
        : param image_names: 要加载的图像名称列表
        : param groups : 要添加到的精灵组
        """
        # 调用父类方法实现精灵的创建
        super().__init__(image_names[0],0, *groups)
        # 加载图像
        self.images = [pygame.image.load(self.res_path + name) for name in image_names]
    def switch_status(self,is_pause):
        """切换状态
        : param is_pause: 是否暂停
        """

        self.image = self.images[1 if is_pause else 0]
class Label(pygame.sprite.Sprite):
    """文本标签精灵"""
    font_path ="./res/font/MarkerFelt.ttc"          # 字体文件路径

    def __init__(self, text, size, color, *groups):
        """初始化方法
        : param text: 文本内容
        : param size: 字体大小
        : param color: 字体颜色
        : param groups: 要添加到的精灵组
        """
        # 调用父类方法实现精灵的创建
        super().__init__(*groups)

        self.font = pygame.font.Font(self.font_path,size)
        self.color = color
        self.image = self.font.render(text,True,self.color)
        self.rect = self.image.get_rect()

    def set_text(self,text):
        """设置文本，使用指定的文本重新渲染 image, 并且更新 rect
        : param text: 文本内容
        """
        self.image = self.font.render(text,True,self.color)
        self.rect = self.image.get_rect()   

class Plane(GameSprite):
    """飞机类"""
    def __init__(self,hp, speed, value, wav_name,
                 normal_names, hurt_name, destroy_names, *groups):
        super().__init__(normal_names[0], speed, *groups)

        self.hp = hp
        self.max_hp = hp
        self.value = value
        self.wav_name = wav_name

        self.normal_images = [pygame.image.load(self.res_path + name) for name in normal_names]
        self.normal_index = 0

        self.hurt_image = pygame.image.load(self.res_path + hurt_name) 

        self.destroy_images = [pygame.image.load(self.res_path + name) for name in destroy_names]
        self.destroy_index = 0

    # def update(self, *args):
    #     # 如果第0个参数为 False, 不需要更新图像，直接返回
    #     if not args[0]:
    #         return
    #     # 设置图像
    #     self.image = self.normal_images[self.normal_index]
    #     # 更新索引
    #     count = len(self.normal_images)
    #     self.normal_index = (self.normal_index + 1) % count   

    def reset_plane(self):
        self.hp = self.max_hp
        self.normal_index = 0
        self.destroy_index = 0
        self.image = self.normal_images[0]

    def update(self, *args):
        #如果第0 个参数为False， 不需要更新图像，直接返回
        if not args[0]:
            return
        # 判断飞机状态
        if self.hp == self.max_hp:              # 未受伤
            self.image = self.normal_images[self.normal_index]
            # 更新索引
            count = len(self.normal_images)
            self.normal_index = (self.normal_index + 1) % count
        elif self.hp > 0:                       # 受伤
            self.image = self.hurt_image
        else:
            # 判断是否显示到最后一张图像，如果是说明飞机完全被摧毁
            if self.destroy_index < len(self.destroy_images):
                self.image = self.destroy_images[self.destroy_index]
                self.destroy_index += 1
            else:
                self.reset_plane()              # 重置飞机    
class Enemy(Plane):
    def __init__(self, kind, max_speed, *groups):
        self.kind = kind
        self.max_speed = max_speed
        if kind == 0:
            super().__init__(1,1, 1000,"enemy1_down.wav",
                            ["enemy1.png"],
                            "enemy1.png",
                            ["enemy1_down%d.png" % i for i in range(1,5)],
                            *groups)
        elif kind == 1:
            super().__init__(6,1, 6000,"enemy2_down.wav",
                            ["enemy2.png"],
                            "enemy2_hit.png",
                            ["enemy2_down%d.png" % i for i in range(1,5)],
                            *groups)
        else:
            super().__init__(15,1, 15000,"enemy3_down.wav",
                            ["enemy3_n1.png", "enemy3_n2.png"],
                            "enemy3_hit.png",
                            ["enemy3_down%d.png" % i for i in range(1,7)],
                            *groups)
        self.reset_plane()
    def reset_plane(self):
        """重置飞机"""
        super().reset_plane()
        # 设置随机位置
        x = random.randint(0, SCREEN_RECT.w - self.rect.w)
        y = random.randint(0, SCREEN_RECT.h - self.rect.h) - SCREEN_RECT.h
        #y = random.randint(0,SCREEN_RECT.h - self.rect.h)
        self.rect.topleft = (x,y)
        self.speed = random.randint(1, self.max_speed)

    def update(self, *args):
        """更新图像和位置"""
        super().update(*args)
        if self.hp > 0:
            self.rect.y += self.speed
        if self.rect.y >= SCREEN_RECT.h:
            self.reset_plane()

class Hero(Plane):
    def __init__(self, *groups):
        super().__init__(1000,5,0, "me_down.wav",
                            ["me%d.png" % i for i in range(1,3)],
                            "me1.png",
                            ["me_destroy_%d.png" % i for i in range(1,5)],
                            *groups)
        self.is_power = False
        self.bomb_count = HERO_BOMB_COUNT
        self.bullets_kind = 0
        self.bullets_group = pygame.sprite.Group()
        #初始位置
        self.rect.midbottom = HERO_DEFAULT_MID_BOTTOM

        pygame.time.set_timer(HERO_FIRE_EVENT,200)


    def update(self, *args):
        super().update(*args)
        if len(args) != 3 or self.hp <= 0:
            return
        self.rect.x += args[1] * self.speed
        self.rect.y += args[2] * self.speed
        self.rect.x = 0 if self.rect.x < 0 else self.rect.x
        if self.rect.right > SCREEN_RECT.right:
            self.rect.right = SCREEN_RECT.right
        self.rect.y = 0 if self.rect.y < 0 else self.rect.y
        if self.rect.bottom > SCREEN_RECT.bottom:
            self.rect.bottom = SCREEN_RECT.bottom

    def blowup(self, enemies_group):
        """引爆炸弹
        enemies_group:敌机精灵组
        return:累计得分"""
        if self.bomb_count <= 0 or self.hp <= 0:
            return 0
        self.bomb_count -= 1
        score = 0
        count = 0
        #遍历敌机精灵组，将游戏窗口内的敌机引爆
        for enemy in enemies_group.sprites():
            if enemy.rect.bottom > 0:
                score += enemy.value
                count += 1
                enemy.hp = 0
        print("炸毁了%d架敌机,得分 %d" % (count, score))
        return score


    def reset_plane(self):
        super().reset_plane()
        self.is_power = True
        self.bomb_count = HERO_BOMB_COUNT
        self.bullets_kind = 0
        pygame.event.post(pygame.event.Event(HERO_DEAD_EVENT))
        pygame.time.set_timer(HERO_POWER_OFF_EVENT, 3000)

    def fire(self, display_group):
        groups = (self.bullets_group, display_group)
        #测试子弹增强效果
        #self.bullets_kind = 1

        for i in range(3):
            bullet1 = Bullet(self.bullets_kind, *groups)
            y = self.rect.y - i * 15
            if self.bullets_kind == 0:
                bullet1.rect.midbottom = (self.rect.centerx, y)
            else:
                bullet1.rect.midbottom = (self.rect.centerx - 20, y)
                bullet2 = Bullet(self.bullets_kind, *groups)
                bullet2.rect.midbottom = (self.rect.centerx + 20, y)

class Bullet(GameSprite):
    def __init__(self, kind, *groups):
        image_name = "bullet1.png" if kind == 0 else "bullet2.png"
        super().__init__(image_name, -12, *groups)
        self.damage = 1
    def update(self, *args):
        super().update(*args)
        #判断是否从上方飞出窗口
        if self.rect.bottom < 0:
            self.kill()

        
class Supply(GameSprite):
    def __init__(self, kind, *groups):
        #调用父类方法
        image_name = "%s_supply.png" % ("bomb" if kind == 0 else "bullet")
        super().__init__(image_name, 5, *groups)
        #道具类型
        self.kind = kind
        #音频文件名
        self.wav_name = "get_%s.wav" % ("bomb" if kind == 0 else "bullet")
        #初始位置
        self.rect.y = SCREEN_RECT.h
    def throw_supply(self):
        #投放道具
        self.rect.bottom = 0
        self.rect.x = random.randint(0, SCREEN_RECT.w - self.rect.w)
    def update(self, *args):
        if self.rect.h > SCREEN_RECT.h:
            return 
        super().update(*args)
    